﻿using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Zhao.Common.JWT;
using Zhao.IServer.Log;
using Zhao.Models.DTO;
using Zhao.Models.Entity;

namespace Zhao.AuthServer.JwtService
{
    /// <summary>
    /// 对称可逆加密实现
    /// </summary>
    public class CustomHSJWTService : CustomJWTService
    {
        private readonly JWTTokenOptions _JWTTokenOptions;
        private readonly IMemoryCache _IMemoryCache;//内存缓存的一个帮助类库
        public CustomHSJWTService(IOptionsMonitor<JWTTokenOptions> jwtTokenOptions, IMemoryCache iMemoryCache)
        {
            if (jwtTokenOptions.CurrentValue == null)
            {
                throw new Exception("没有配置Jwt 秘钥~");
            }
            _JWTTokenOptions = jwtTokenOptions.CurrentValue;
            _IMemoryCache = iMemoryCache;
        }

        /// <summary>
        /// 对称可逆加密生成Token
        /// </summary>
        /// <param name="admin"></param>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        public override string CreateToken(AdminInfoDto logInDto, out string refreshToken)
        {
            //准备有效载荷
            List<Claim> claimsArray = base.UserToClaim(logInDto);
            //准备加密key
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_JWTTokenOptions.SecurityKey!));

            //Sha256 加密方式
            SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            JwtSecurityToken JwtAccessToken = new JwtSecurityToken(
                  issuer: _JWTTokenOptions.Issuer,
                  audience: _JWTTokenOptions.Audience,
                  claims: claimsArray.ToArray(),
                  expires: DateTime.Now.AddHours(5),
                  signingCredentials: creds
            );
            string accesstoken = new JwtSecurityTokenHandler().WriteToken(JwtAccessToken);

            //生成refreshtoken
            string refreshtokenGuid = Guid.NewGuid().ToString();
            claimsArray.Add(new Claim("refreshtokenGuid", refreshtokenGuid));
            JwtSecurityToken JwtRefreshToken = new JwtSecurityToken(
               issuer: _JWTTokenOptions.Issuer,
               audience: _JWTTokenOptions.Audience,
               claims: claimsArray.ToArray(),
               expires: DateTime.Now.AddHours(6),
               signingCredentials: creds //加密方式
            );

            refreshToken = new JwtSecurityTokenHandler().WriteToken(JwtRefreshToken);

            //将信息存储到缓存中
            _IMemoryCache.Set(refreshtokenGuid, logInDto, DateTime.Now.AddHours(6));
            return accesstoken;
        }
    }
}
